var __spaceRe = / /g;
var __formatRe = /%(\d+)/g;
var __isFormatReOK = __format_new(new Array('%1', '1')) == '1';


if (!document.all)
{
	Event.prototype.__defineGetter__("srcElement", function()
	{
		var node = this.target;
		while (node.nodeType != 1)
			node = node.parentNode;
		return node;
	});

	var allGetter = function()
	{
		var a = this.getElementsByTagName("*");
		var node = this;
		a.tags = function(sTagName)
		{
			return node.getElementsByTagName(sTagName);
		};
		return a;
	};

	HTMLDocument.prototype.__defineGetter__("all", allGetter);
	HTMLElement.prototype.__defineGetter__("all", allGetter);

	function emulateProc(e)
	{
		window.event = e;
	}

	function emulateEventHandlers(eventNames)
	{
		for (var i = 0; i < eventNames.length; i++)
		{
			document.addEventListener(eventNames[i], emulateProc, true); // using capture
		}
	}

	function releaseEmulatedEventHandlers(eventNames)
	{
		for (var i = 0; i < eventNames.length; i++)
		{
			document.removeEventListener(eventNames[i], emulateProc, true); // using capture
		}
	}

	function releaseHandlers()
	{
		releaseEmulatedEventHandlers(["click", "mousemove"]);
		window.event = null;
		window.removeEventListener('unload', releaseEmulatedEventHandlers, false);
	}

	emulateEventHandlers(["click", "mousemove"]);
	window.addEventListener('unload', releaseHandlers, false);
}

// http://laurens.vd.oever.nl/weblog/items2005/closures/
if (!Function.prototype.closure)
{
	Function.prototype.closure = function(obj)
	{
	  // Init object storage.
	  if (!window.__objs)
	  {
	    window.__objs = [];
	    window.__funs = [];
	  }
	
	  // For symmetry and clarity.
	  var fun = this;
	
	  // Make sure the object has an id and is stored in the object store.
	  var objId = obj.__objId;
	  if (!objId)
	    __objs[objId = obj.__objId = __objs.length] = obj;
	
	  // Make sure the function has an id and is stored in the function store.
	  var funId = fun.__funId;
	  if (!funId)
	    __funs[funId = fun.__funId = __funs.length] = fun;
	
	  // Init closure storage.
	  if (!obj.__closures)
	    obj.__closures = [];
	
	  // See if we previously created a closure for this object/function pair.
	  var closure = obj.__closures[funId];
	  if (closure)
	    return closure;
	
	  // Clear references to keep them out of the closure scope.
	  obj = null;
	  fun = null;
	
	  // Create the closure, store in cache and return result.
	  return __objs[objId].__closures[funId] = function ()
	  {
	    return __funs[funId].apply(__objs[objId], arguments);
	  };
	};
}

// http://phrogz.net/JS/Classes/OOPinJS2.html
if (!Function.prototype.inheritsFrom)
{
	Function.prototype.inheritsFrom = function(parentClassOrObject, className)
	{
		var p;
		if (parentClassOrObject.constructor == Function)
		{
			//Normal Inheritance 
			p = this.prototype = new parentClassOrObject;
			p.constructor = this;
			p.parentObject = parentClassOrObject.prototype;
		}
		else
		{
			//Pure Virtual Inheritance 
			p = this.prototype = parentClassOrObject;
			p.constructor = this;
			p.parentObject = parentClassOrObject;
		}
		if (className)
			p.className = className;

		return this;
	};
}

if (!Array.prototype.indexOf)
{
	Array.prototype.indexOf = function(o, startIndex)
	{
		if (startIndex == null)
			startIndex = 0;

		for (var i = startIndex; i < this.length; i ++)
		{
		  if (this [i] === o)
		    return i;
		}

		return -1;
	};
}

if (!Array.prototype.lastIndexOf)
{
	Array.prototype.lastIndexOf = function (obj, startIndex)
	{
		if ((startIndex == null) || (startIndex >= this.length))
			startIndex = this.length - 1;
			
		for (var i = startIndex; i >= 0; i --) 
		{
		  if (this [i] === obj)
		    return i;
		}

		return -1;
	};
}

if (!Array.prototype.clear)
{
	Array.prototype.clear = function(associative)
	{
		this.length = 0;

		if (associative)
			for (var name in this)
			{
				if (Array.prototype[name] != null)
					continue;

				delete this[name];
			}
	};
}

if (!Array.prototype.clone)
{
	Array.prototype.clone = function()
	{
		var newArr = [];
		for (var prop in this)
		{
			if (Array.prototype[prop] != null)
				continue;

			newArr[prop] = this[prop];
		}

		return newArr;
	};
}

if (!Array.prototype.contains)
{
    Array.prototype.contains = function(o)
    {
    	return this.indexOf(o) != -1;
    };
}

if (!Array.prototype.copy)
{
    Array.prototype.copy = function(addItems)
    {
    	if (addItems)
    		return this.concat(addItems);
    	else
    		return this.concat();
    };
}

if (!Array.prototype.copyFrom)
{
    Array.prototype.copyFrom = function(arr)
    {
      for (var i = 0; i < arr.length; i++)
        this.push(arr[i]);
    };
}

if (!Array.prototype.insertAt)
{
    Array.prototype.insertAt = function (pos, items)
    {
    	this.splice (pos, 0, items);
    };
}

if (!Array.prototype.removeAt)
{
    Array.prototype.removeAt = function(index)
    {
    	this.splice(index, 1);
    };
}

if (!Array.prototype.remove)
{
    Array.prototype.remove = function(obj)
    {
    	var i = this.indexOf(obj);
    	if (i != -1)
    	 this.splice(i, 1);
    };
}

if (!Array.prototype.splice)
{
	Array.prototype.splice = function(start, deleteCount)
	{
		var i, arg = 2;
		var addCount = arguments.length - 2;
		var moveCount = addCount - deleteCount;

		if (moveCount < 0)
		{
			moveCount = Math.abs(moveCount);
			for (i = start; i <= this.length - moveCount; i++)
				this[i] = this[i + moveCount];

			this.length -= Math.min(moveCount, this.length - start);
		}
		else
		{
			this.length += moveCount;

			for (i = this.length - 1; i > start; i--)
				this[i] = this[i - moveCount];
		}

		for (i = start; i < start + addCount; i++)
			this[i] = arguments[arg++];

	};
}

if (!Array.prototype.forEach)
{
	Array.prototype.forEach = function (func, objContext)
	{
		var len = this.length;
		if (len == 0)
			return;

		var i = len;

		do
		{
			if (this.length <= len - i)
			    break;

			var item = this[len - i];
			if (! (typeof(item) == 'undefined'))
				func.call(objContext, this[len - i], len - i);
		}
		while (--i);

//		for (var i = 0; i < this.length; i++)
//		  func.call(objContext, this[i], i);
	};
}

if (!Array.prototype.forEachRev)
{
	Array.prototype.forEachRev = function (func, objContext)
	{
		var len = this.length;
		if (len == 0)
			return;

		var i = len;
		do
		{
			func.call(objContext, this[i - 1], i - 1);
		}
		while (--i);

//		for (var i = this.length - 1; i >= 0; i--)
//		  func.call(objContext, this[i], i);
	};
}

if (!Array.prototype.forIn)
{
	Array.prototype.forIn = function (func, objContext)
	{
		for (var name in this)
		{
          if (Array.prototype[name] != null)
            continue;

		  func.call(objContext, this[name], name);
		}
	};
}


if (!Array.prototype.push)
{
	Array.prototype.push = function (item)
	{
	  this[this.length++] = item;
	};
}

if(!Array.prototype.pop)
{
	Array.prototype.pop = function()
	{
		var item = this[this.length - 1];
		this.length--;
		return item;
	};
}

if(!Array.prototype.shift)
{
	Array.prototype.shift = function()
	{
		if (this.length == 0)
			return null;

		var item = this[0];
		this.removeAt(0);
		return item;
	};
}


if(!String.prototype.startsWith)
{
	String.prototype.startsWith = function(str)
	{
		return (this.substr(0, str.length) == str);
	};
}

if(!String.prototype.endsWith)
{
	String.prototype.endsWith = function (str) 
	{
		return (this.substr(this.length - str.length, str.length) == str);
	};
}

if (!String.prototype.padLeft)
{
    String.prototype.padLeft = function (totalWidth, paddingChar)
    {
    	if ((totalWidth == null) || (totalWidth == 0) || (this.length >= totalWidth))
    		return this;

    	var padStr = '                                                                                                    ';
    	padStr = padStr.substr(0, totalWidth - this.length); 

    	if ((paddingChar == null) || (paddingChar == ' '))
    		return padStr + this;
    	else
    		return padStr.replace(__spaceRe, paddingChar) + this;
    };
}

if(!String.prototype.trimStart)
{
	String.prototype.trimStart = function()
	{
		var whitespace = new String(" \t\n\r");

		var s = new String(this);

		if (whitespace.indexOf(s.charAt(0)) != -1)
		{
			var j = 0, i = s.length;

			while (j < i && whitespace.indexOf(s.charAt(j)) != -1)
				j++;

			s = s.substring(j, i);
		}
		return s;
	};
}

if(!String.prototype.trimEnd)
{
	String.prototype.trimEnd = function()
	{
		var whitespace = new String(" \t\n\r");

		var s = new String(this);

		if (whitespace.indexOf(s.charAt(s.length-1)) != -1)
		{
			var i = s.length - 1;

			while (i >= 0 && whitespace.indexOf(s.charAt(i)) != -1)
				i--;

			s = s.substring(0, i+1);
		}

		return s;
	};
}

if(!String.prototype.trim)
{
	String.prototype.trim = function()
	{
		return this.trimStart().trimEnd();
	};
}

if(!String.prototype.urlEncode)
{
	String.prototype.urlEncode = function()
	{
		return utils.urlEncode(this);
	};
}

if(!String.prototype.urlDecode)
{
	String.prototype.urlDecode = function()
	{
		return utils.urlDecode(this);
	};
}

if (!String.prototype.escapeHtmlTags) {
    String.prototype.escapeHtmlTags = function () {
        return this.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    }
}

if (!Number.prototype.padLeft)
{
	Number.prototype.padLeft = function (totalWidth, paddingChar)
	{
		return this.toString().padLeft(totalWidth, (paddingChar != null) ? paddingChar : '0');
	};
}


if (!this.browser)
{

	if (bowser){
		browser = new Object();
		browser.isIE =  bowser.msie == true;
		browser.isGeckoBased = bowser.gecko == true;
		browser.isFirefox = bowser.firefox == true;
		browser.isChrome = bowser.chrome == true;
		browser.isWebKit = bowser.webkit == true;
		browser.isOpera = bowser.opera == true;
		browser.version = parseFloat(bowser.version);
	} else {
		//just to be sure
		browser = new Object();
		browser.isIE =  /MSIE/.test(navigator.userAgent);
		browser.isGeckoBased = navigator.product == 'Gecko';
		browser.isFirefox = /Firefox/.test(navigator.userAgent);
		browser.isChrome = /Chrome/.test(navigator.userAgent);
		browser.isWebKit = /WebKit/.test(navigator.userAgent);
		browser.isOpera = navigator.userAgent.indexOf('Opera') > -1;
		if (browser.isIE)
		{
			/MSIE\s(\d\.\d);/.test(navigator.userAgent);
			browser.version = parseFloat(RegExp.$1);
		}
		else
			browser.version = parseFloat(navigator.appVersion.substr(0, navigator.appVersion.indexOf(' ')));
	}
/*	
	s = 'browser.isIE ' + browser.isIE +
	'\nbrowser.isGeckoBased ' + browser.isGeckoBased +
	'\nbrowser.isFirefox ' + browser.isFirefox +
	'\nbrowser.isChrome ' + browser.isChrome +
	'\nbrowser.isWebKit ' + browser.isWebKit +
	'\nbrowser.isOpera ' + browser.isOpera +
	'\nbrowser.version ' + browser.version;
	
	alert(s);
*/
}

if (!this.utils)
{
	utils = new Object();

	utils.attachEvent = function(el, eventName, funcToCall)
	{
		if (el.addEventListener)
		{
			el.addEventListener(eventName, funcToCall, false); 
		}
		else
		if (el.attachEvent)
		{
			el.attachEvent('on' + eventName, funcToCall);
		}
	};

	utils.detachEvent = function(el, eventName, funcToCall)
	{
		if (el.removeEventListener)
		{
			el.removeEventListener(eventName, funcToCall, false); 
		}
		else
		if (el.detachEvent)
		{
			try
			{
				el.detachEvent('on' + eventName, funcToCall);
			}
			catch(e)
			{
//				var msg = e.Message;
			}
		}
	};

	utils.lastAjaxCallStatus = null;
	utils.ajaxRequestCounter = 0;
	utils.ajaxCall = function (postGet, strURL, strSubmit, encType, async, strResultFunc, timeout)
	{
		var xmlHttpReq = null;

		// Mozilla/Safari/IE7
		if (window.XMLHttpRequest)
		{
			xmlHttpReq = new XMLHttpRequest();
			if (xmlHttpReq.overrideMimeType)
				xmlHttpReq.overrideMimeType('text/xml');
		}
		// IE
		else
		if (window.ActiveXObject)
		{
			try
			{
				xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
			}
			catch (e)
			{
				try
				{
					xmlHttpReq = new ActiveXObject("Msxml2.XMLHTTP");
				}
				catch (e) {}
			}
		}
		else 
		if (window.createRequest)
		{
			try
			{
				xmlHttpReq = window.createRequest();
			}
			catch (e) {}
		}

		strURL += ((strURL.indexOf('?') == -1) ? '?' : '&') + 'reqCounter=' + (utils.ajaxRequestCounter++).toString();  
 
		xmlHttpReq.open(postGet, strURL, async);

		if (postGet.toLowerCase() == 'post')
		{
			xmlHttpReq.setRequestHeader('Content-Type', ((encType != null) && (encType != '')) ? encType : 'application/x-www-form-urlencoded');
		}

		if ((async) && (strResultFunc != null))
		{
			if (timeout == null)
				timeout = 180000;

			if (!appDebugEnabled)
			{
				window.setTimeout
				(function()
					{
						if (xmlHttpReq != null)
						{
							var icdisp = false;
							try
							{
								icdisp = xmlHttpReq.getResponseHeader('X-ICDISP');
							}
							catch(e) {}

							xmlHttpReq.abort();
							strResultFunc.call(this, -1, null);
							try
							{
								xmlHttpReq.onreadystatechange = null;
							}
							catch (e){}
							xmlHttpReq = null;
						}
					}
				, timeout
				);
			}
		
			xmlHttpReq.onreadystatechange = function()
			{
				if ((xmlHttpReq.readyState == 4) && (xmlHttpReq.status != 0))
				{
//					eval('strResultFunc.call(this, xmlHttpReq.status, xmlHttpReq.responseText)');
					var icdisp = false;
					try
					{
						icdisp = xmlHttpReq.getResponseHeader('X-ICDISP');
					}
					catch(e) {}

					strResultFunc.call(this, xmlHttpReq.status, xmlHttpReq.responseText);
					try
					{
						xmlHttpReq.onreadystatechange = null;
					}
					catch (e){}
					xmlHttpReq = null;
				}
			};
		}

		try
		{
			xmlHttpReq.send(strSubmit);
		}
		catch (e)
		{
			alert('Chyba při komunikaci se serverem!\nAn error occurred during the communication with the server!\n\n' + e.message);
		}

		if (!async)
		{
			utils.lastAjaxCallStatus = xmlHttpReq.status;
			return xmlHttpReq.responseText;
		}
	};
    
	utils.buildArgumentString = function(args, name)
	{
		var i;
		var argStr = "";
		if (utils.isEmpty(name))
			name = 'arguments';

		for (i = 0; i < args.length; i++)
		{
			if (i < args.length - 1)
				argStr += name +'[' + i + '],';
			else
				argStr += name + '[' + i + ']';
		}
		return argStr;
	};

	utils.cancelEvent = function(event)
	{
		if (event == null)
			event = window.event;

		if (event != null)
		{
			if (browser.isIE)
			{
				event.returnValue = false;
				event.cancelBubble = true;
			}
			else
			{
				event.preventDefault();
				event.stopPropagation();
			}
		}
	};

	utils.cancelSelect = function(args, wnd)
	{
		if (browser.isIE)
		{
			if (wnd == null)
				wnd = window;

			if ((wnd.event.srcElement.tagName != "INPUT") && (wnd.event.srcElement.tagName != "TEXTAREA"))
			{
				wnd.event.returnValue = false;
				wnd.event.cancelBubble = true;
				return false;
			}
			return true;
		}
		else
		{
			var e = args[0];
			if ((e.target.tagName != "INPUT") && (e.target.tagName != "TEXTAREA"))
			{
				e.preventDefault();
				e.stopPropagation();
				return false;
			}
			return true;
		}
	};

	utils.coalesce = function(/* optional number of arguments */)
	{
		var argLen = arguments.length;
		for (var i = 0; i < argLen; i++)
		{
			if (arguments[i] != null)
				return (arguments[i]);
		}
		return (null);
	};

	utils.clone = function(objectToClone)
	{
		var objectType = objectToClone.constructor.toString() || "Object";
		var newObject = new objectType;

		for (var prop in objectToClone)
			newObject[prop] = objectToClone[prop];

		return newObject;
	};

	utils.createXMLDocument = function (xmlString)
	{
		var myDocument = null;

		if (document.implementation.createDocument)
		{
			// Mozilla, create a new DOMParser
			var parser = new DOMParser();
			myDocument = parser.parseFromString(xmlString, "text/xml");
		}
		else
		if (window.ActiveXObject)
		{
			// Internet Explorer, create a new XML document using ActiveX
			// and use loadXML as a DOM parser.
			myDocument = new ActiveXObject("Microsoft.XMLDOM");
			myDocument.async="false";
			myDocument.loadXML(xmlString);
		}

		return myDocument;
	};

	function daysInMonth(year, month)
	{
		if (year == null)
			year = (new Date()).getFullYear();

		if (month == null)
			month = (new Date()).getMonth();
		else
			month--;

		var d = new Date(year, month, 1);
		d.setMonth(d.getMonth() + 1);
		d.setDate(0);

		return d.getDate();
	}

	utils.format = function()
	{
		if (__isFormatReOK)
			return __format_new(arguments);
		else
			return __format_old(arguments);
	};

	utils.getCtrlKey = function(event)
	{
		if (browser.isIE)
			event = window.event;

		if (event == null)
			return false;

		return event.ctrlKey;
	};

	utils.getElementBox = function(element)
	{
		var rect = {x: -1, y: -1, width: -1, height:-1};
		if (document.getBoxObjectFor)
		{
			var box = document.getBoxObjectFor(element);
			rect.x = box.x;
			rect.y = box.y;
			rect.width = box.width;
			rect.height = box.height;
		}
		else
		if (element.getBoundingClientRect)
		{
			var cr = element.getBoundingClientRect();
			rect.x = cr.left;
			rect.y = cr.top;
			rect.width = cr.right - cr.left;
			rect.height = cr.bottom - cr.top;
		}

		rect.left = rect.x;
		rect.top = rect.y;

		return rect; 
	};

	utils.getElementPosition = function(obj, doc)
	{
		if (!doc)
			doc = document;

		if (typeof obj == 'string')
			obj = (doc) ? doc.getElementById(obj) : doc.getElementById(obj);

		var obj2 = obj;
		var curtop = 0;
		var curleft = 0;
		if (doc.getElementById || doc.all)
		{
			do
			{
				curleft += obj.offsetLeft - obj.scrollLeft;
				curtop += obj.offsetTop - obj.scrollTop;
				obj = obj.offsetParent;
				obj2 = obj2.parentNode;
				while (obj2 != obj)
				{
					curleft -= obj2.scrollLeft;
					curtop -= obj2.scrollTop;
					obj2 = obj2.parentNode;
				}
			} while ((obj) && (obj.offsetParent))
		} else if (doc.layers)
		{
			curtop += obj.y;
			curleft += obj.x;
		}
		return { left: curleft, top: curtop };
	};

	utils.getElementPosition2 = function(element, doc)
	{
		var offsetTrail = element;
		if (typeof element == 'string')
			offsetTrail = (doc) ? doc.getElementById(element) : document.getElementById(element);  

		var offsetLeft = 0;
		var offsetTop = 0;
		while(offsetTrail)
		{
			offsetLeft += offsetTrail.offsetLeft;
			offsetTop += offsetTrail.offsetTop;

			if (offsetTrail.tagName != 'INPUT')
			{
				offsetLeft -= offsetTrail.scrollLeft;
				offsetTop -= offsetTrail.scrollTop;
			}

			offsetTrail = offsetTrail.offsetParent;
		}

		if ((navigator.userAgent.indexOf("Mac") != -1) && (typeof(document.body.leftMargin) != "undefined"))
		{
			offsetLeft += parseInt(document.body.leftMargin);
			offsetTop += parseInt(document.body.topMargin);
	 	}

	 	return { left: offsetLeft, top: offsetTop };
	};

	utils.getElementPosition3 = function(element, doc)
	{
		var result = new Object();
		result.left = 0;
		result.top = 0;
		result.width = 0;
		result.height = 0;

		if (typeof element == 'string')
			element = (doc) ? doc.getElementById(element) : document.getElementById(element);

		if (element.offsetParent)
		{
			result.left = element.offsetLeft;
			result.top = element.offsetTop;
			var parent = element.offsetParent;
			while (parent)
			{
				result.left += parent.offsetLeft;
				result.top += parent.offsetTop;
				var parentTagName = parent.tagName.toLowerCase();
				if (parentTagName != "table" &&
				    parentTagName != "body" &&
				    parentTagName != "html" &&
				    parentTagName != "div" &&
				    parent.clientTop &&
				    parent.clientLeft)
				{
					result.left += parent.clientLeft;
					result.top += parent.clientTop;
				}
				parent = parent.offsetParent;
			}
		}
		else
		if (element.left && element.top)
		{
			result.left = element.left;
			result.top = element.top;
		}
		else
		{
			if (element.x)
			{
				result.left = element.x;
			}
			if (element.y)
			{
				result.top = element.y;
			}
		}
		if (element.offsetWidth && element.offsetHeight)
		{
			result.width = element.offsetWidth;
			result.height = element.offsetHeight;
		}
		else
		if (element.style && element.style.pixelWidth && element.style.pixelHeight)
		{
			result.width = element.style.pixelWidth;
			result.height = element.style.pixelHeight;
		}

		return result;
	};

	utils.getEventElement = function(args)
	{
		var elem = null;
		if (((args == null) || (args.length == 0)) && (window.event))
		{
			if (window.event.type == "mouseover")
				elem = window.event.toElement;
			else
				elem = window.event.fromElement;

			if (elem == null)
			  elem = window.event.srcElement;
		}
		else
		if (args.target)
		{
			elem = args.target; 
		}
	
		return elem;
	};


	utils.getMouseXY = function(event)
	{
		if (browser.isIE)
		{
			if (window.event.clientX != null)
				return {x: window.event.clientX, y: window.event.clientY};
			else
				return {x: window.event.x, y: window.event.y};
	    }
		else
		{
			return {x: event.clientX, y: event.clientY};
		}
	};

	utils.getParentZIndex = function(elem)
	{
		if (elem == null)
			return 0;

		elem = elem.parentNode;
		var zIndex = parseInt(utils.getStyle(elem, 'zIndex'));
		if (isNaN(zIndex))
			zIndex = 0;

		while ((elem.parentNode != null) && (zIndex == 0))
		{
			elem = elem.parentNode;
			try
			{
				zIndex = parseInt(utils.getStyle(elem, 'zIndex'));
				if (isNaN(zIndex))
					zIndex = 0;
			}
			catch(e)
			{
				zIndex = 0;
			}
		}

		return zIndex;
	};


	utils.getStyleRule = function(selectorText, iSheet, doc)
	{
		var sheets = (doc != null) ? doc.styleSheets : document.styleSheets;
		if(!sheets)
			return null;

		var sheet = sheets[ isNaN(iSheet)? sheets.length-1 : iSheet];
		var rules = sheet.cssRules || sheet.rules;

		var style = new Object;
		var cnt = 0;

		for(var i = 0; i < rules.length; i++)
		{
			var rule = rules[i];
			if(rule.selectorText == selectorText)
			{
				for (var prop in rule.style)
				{
					if (cnt == 0)
						style[prop] = rule.style[prop];
					else
					if (rule.style[prop] != "") 
						style[prop] = rule.style[prop];

					cnt++;
				}
			}
		}

		if (cnt == 0)
			return null;

		return style;
	};

	utils.getStyle = function (element, cssRule)
	{
		if (element == null)
			return null;

		var value;
		if (document.defaultView && document.defaultView.getComputedStyle)
		{
			var propName;
			if (__isFormatReOK)
			{
				propName = cssRule.replace( /[A-Z]/g, function(char, index)
					{
						return "-" + char.toLowerCase();
					});
			}
/*
			else
			{
				var dashIndex;
				propName = cssRule;
				while((dashIndex = propName.indexOf('-')) != -1)
				{
				propName = propName.substring(0,dashIndex) + propName.substring(dashIndex + 1, dashIndex + 2).toUpperCase() + propName.substring(dashIndex + 2);
				}
			}
*/
			value = document.defaultView.getComputedStyle(element, '').getPropertyValue(propName);
		}
		else
			if (element.currentStyle)
				value = element.currentStyle[cssRule];
			else
				value = false;

		return value;
	};

	utils.isEmpty = function(obj)
	{
		if (obj == null)
			return true;

		if ((obj == "") && (typeof obj == "string"))
			return true;

		return false;
	};

	utils.inList = function (item)
	{
		var argLen = arguments.length;
		for (var i = 1; i < argLen; i++)
		{
			if (item == arguments[i])
				return (true);
		}

		return (false);
	};

	utils.inSet = function(item, set)
	{
		return ((set & item) == item);
	};

	utils.instanceOf = function (object, constructor)
	{
		while (object != null)
		{
			if (object == constructor.prototype)
				return true;
			object = object.__proto__;
		}

		return false;
	};

	utils.parseBool = function(value)
	{
		if (value == null)
			return false;

		if (value.constructor == Boolean)
			return value;

		if (value.constructor == Number)
			return (value == 1);

		if (value.constructor == String)
			return ((value.toLowerCase() == "true") || (value.toLowerCase() == "1"));

		return false;
	};

	utils.purgeHTML = function(elem)
	{
		if (elem == null)
			return;

		var coll = elem.attributes;
		var i, len, name;

		if (coll)
		{
			len = coll.length;
			for (i = 0; i < len; i++)
			{
				name = coll[i].name;
				if (typeof elem[name] == 'function')
					elem[name] = null;
			}
		}

		coll = elem.childNodes;
		if (coll)
		{
			len = coll.length;
			for (i = 0; i < len; i++)
				arguments.callee(coll[i]);
		}
	};

	utils.setCaretToEnd = function(control)
	{
		if (control.createTextRange)
		{
			var range = control.createTextRange();
			range.collapse(false);
			range.select();
		}
		else
		if (control.setSelectionRange)
		{
			control.focus();
			var length = control.value.length;
			control.setSelectionRange(length, length);
		}
	};

	utils.setCaretToStart = function(control)
	{
		if (control.createTextRange)
		{
			var range = control.createTextRange();
			range.collapse(true);
			range.select();
		}
		else
		if (control.setSelectionRange)
		{
			control.focus();
			control.setSelectionRange(0, 0);
		}
	};

	utils.selectText = function(control)
	{
		if (control.createTextRange)
		{
			var range = control.createTextRange();
			range.expand('textedit');
			range.select();
		}
		else
		if (control.setSelectionRange)
		{
			control.focus();
			control.setSelectionRange(0, control.value.length);
		}
	};

	utils.toInt = function(num, def)
	{
		if (def == null)
			def = 0;

		var n = parseInt(num);
		if (isNaN(n))
			n = def;

		return n;
	};

	utils.wait = function(interval)
	{
		try
		{
			var t1 = (new Date()).getTime();
			while (true)
			{
				var t2 = (new Date()).getTime();
				if ((t2 - t1) > interval)
					break;
			}

		}
		catch(e) { }
	};

	utils.urlEncode = function(clearString)
	{
		var output = '';
		var x = 0;
		clearString = clearString.toString();
		var regex = /(^[a-zA-Z0-9_.]*)/;
		while (x < clearString.length)
		{
			var match = regex.exec(clearString.substr(x));
			if (match != null && match.length > 1 && match[1] != '')
			{
				output += match[1];
				x += match[1].length;
			}
			else
			{
				if (clearString[x] == ' ')
					output += '+';
				else
				{
					var charCode = clearString.charCodeAt(x);
					var hexVal = charCode.toString(16);
					output += '%' + (hexVal.length < 2 ? '0' : '') + hexVal.toUpperCase();
				}
				x++;
			}
		}

		return output;
	};

	utils.urlDecode = function(encodedString)
	{
		var match;
		var output = encodedString;
		var binVal, thisString;
		var myregexp = /(%[^%]{2})/;
		while ((match = myregexp.exec(output)) != null
			&& match.length > 1
			&& match[1] != '')
		{
			binVal = parseInt(match[1].substr(1), 16);
			thisString = String.fromCharCode(binVal);
			output = output.replace(match[1], thisString);
		}

		return output;
	};


	utils.ensureVisible = function(elem)
	{
		if (!elem)
			return;

		var x = 0;
		var y = 0;
		var parent = elem;
		while (parent != null)
		{
			x += parent.offsetLeft;
			y += parent.offsetTop;
			parent = parent.offsetParent;
		}

		var frameTop = (window.frameElement) ? window.frameElement.scrollTop : 0;
		var yView = frameTop + document.body.scrollTop;
		var dyView = document.body.clientHeight;
		var dy = 0;
		if (y + elem.offsetHeight > yView + dyView)
			dy = (y + elem.offsetHeight) - (yView + dyView);
		if (y < yView + dy)
			dy = y - yView;

		var frameLeft = (window.frameElement) ? window.frameElement.scrollLeft : 0;
		var xView = frameLeft + document.body.scrollLeft;
		var dxView = document.body.clientWidth;
		var dx = 0;
		if (x + elem.offsetWidth > xView + dxView)
			dx = (x + elem.offsetWidth) - (xView + dxView);
		if (x < xView + dx)
			dx = x - xView;

		if (dx != 0 || dy != 0)
			window.scrollBy(dx, dy);
	};
	
	utils.sortObj = function(object, sortFunc) {
		var rv = [];
		for (var k in object) {
			if (object.hasOwnProperty(k)) rv.push({key: k, value:  object[k]});
		}
		rv.sort(function(o1, o2) {
			return o1.value.caption.localeCompare(o2.value.caption)
		});
		return rv;
	};

}

function __format_old(args)
{
	var result = args[0];
	for (var i = 1; i < args.length; i++)
	{
		while (result.indexOf("%" + i.toString()) > -1)
		{
			result = result.replace("%" + i.toString(), args[i]);
		}
	}

	return (result);
}

function __format_new(args)
{
	var str = args[0];

	return str.replace(__formatRe, function ($0, $1, $2)
	{
		return args[$1];
	});
}


function JEvent()
{
	var self = this;
	this.eventHandlers = new Array();

	this.attach = function(eventHandler, allowMulti)
	{
		if ((!allowMulti) && (self.eventHandlers.indexOf(eventHandler) > -1))
			return;

		self.eventHandlers.push(eventHandler);
	};

	this.detach = function(eventHandler)
	{
		var idx = self.eventHandlers.indexOf(eventHandler);
		if (idx == -1)
			return;

		self.eventHandlers.splice(idx, 1);
	};

	this.raise = this.dispatch = function()
	{
		var i, args = [], handlers = [];
		args.copyFrom(arguments);

		var scope = args.shift();
		if (scope == null)
			scope = this;

		var argStr = utils.buildArgumentString(args, 'args');

		handlers.copyFrom(self.eventHandlers);
		for (i = 0; i < handlers.length; i++)
		{
			if (utils.isEmpty(argStr))
				handlers[i].call(scope);
			else
				eval('handlers[i].call(scope, ' + argStr + ')');
		}

		args.clear();
		args = null;
	};

	this.dispose = function()
	{
		for (i = 0; i < self.eventHandlers.length; i++)
			self.eventHandlers[i] = null;

		self.eventHandlers.clear();
	};
}


function FastString(initString)
{
	// properties
	this.increment = 1000;
	this.stringArray = new Array(this.increment);
	this.currentIndex = 0;

	// methods
	this.append          = append;
	this.appendFormatted = appendFormatted;
	this.appendFrom      = appendFrom;
	this.toString        = toString;
	this.reset           = reset;
	this.clear           = clear;

	if (initString != null)
	{
		this.stringArray[0] = initString;
		this.currentIndex++;
	}

	function append(string)
	{
		if (this.currentIndex == this.stringArray.length)
			this.stringArray.length += this.increment;

		this.stringArray[this.currentIndex] = string;
		this.currentIndex++;
	}
  
	function appendFormatted(string)
	{
		this.append(format(string, arguments));
	}
  
	function appendFrom(fastString)
	{
		if (fastString.constructor != FastString)
			throw "FastString.appendFrom expects another FastString as parameter.";

		if (this.stringArray.length < (this.currentIndex + fastString.currentIndex))
			this.stringArray.length += fastString.currentIndex;

		for (var i = 0; i < fastString.currentIndex; i++)
		{
			this.stringArray[this.currentIndex] = fastString.stringArray[i];
			this.currentIndex++;
		}
	}
  
	function toString()
	{
		this.stringArray.length = this.currentIndex;
		return this.stringArray.join("");
	}
  
	function reset()
	{
		this.stringArray = new Array(this.increment);
	}
  
	function clear()
	{
		this.reset();
	}
}



/* J R E C T */
function JRect(rect)
{
	var self = this;

	if (rect.constructor == JRect)
	{
		this.left   = rect.left;
		this.top    = rect.top;
		this.width  = rect.width;
		this.height = rect.height;
	}
	else
	{
		var tokens = rect.split(scItemSep);

		this.left   = (tokens[0] != "" ? new Number(tokens[0]) : null);
		this.top    = (tokens[1] != "" ? new Number(tokens[1]) : null);
		this.width  = (tokens[2] != "" ? new Number(tokens[2]) : null);
		this.height = (tokens[3] != "" ? new Number(tokens[3]) : null);
	}

	this.normalize  = normalize;
	this.toString   = toString;
	this.isRelative = isRelative;
	
	function normalize(client)
	{
		self.left   = Math.max(Math.round((client.clientWidth  - self.width)  / 2), fmClientOffset);
		self.top    = Math.max(Math.round((client.clientHeight - self.height) / 2), fmClientOffset);
	}
	
	function toString()
	{
		var result = new Array();

		if (self.left   != null)
			result[result.length++] = "left: "   + self.left   + "px";
		if (self.top    != null)
			result[result.length++] = "top: "    + self.top    + "px";
		if (self.width  != null)
			result[result.length++] = "width: "  + self.width  + "px";
		if (self.height != null)
			result[result.length++] = "height: " + self.height + "px";

		if ((self.left == null) && (self.top == null))
			result[result.length++] = "position: static";

		return (result.join("; "));
	}
	
	function isRelative()
	{
		return ((self.left == null) && (self.top == null));
	}
}


ControlBase = function()
{
	this.base = this;

	this.initialize = function(owner, parent, name, caption, action, rect, flags, field, dataset, tab)
	{
		this.owner = owner;
		this.parent = parent;
		this.name = name;
		this.caption = unescape(caption);
		this.action = action;
		this.rect = (rect) ? new JRect(rect) : new JRect('0;0;0;0');
		this.flags = flags;
		this.methods = cmRender; // (cmRender | cmLoad | cmSave);
		//		this.schema   = fmSchema;
		this.visible = true;
		this.inplace = false;
		this.field = field;
		this.dataset = dataset;
		this.tab = tab;
		this.controls = [];
		this.datasets = [];
		this.isControl = true;
		this.isForm = false;
		this.objectName = "app.getObject('" + this.name + "')";
	};

	this.addControl = function(control)
	{
		var index = this.controls.length;
		this.controls.push(control);

		return index;
	};

	this.removeControl = function(control)
	{
		var index = this.controls.indexOf(control);
		if (index > -1)
			this.controls.removeAt(index);
	};

	this.addDataset = function(dataset)
	{
		var index = this.datasets.length;
		this.datasets.push(dataset);

		return index;
	};

	this.checkPosition = function()
	{
		var ctrls,
		    parentObj = this.getParentObject(),
		    form = this.getForm(),
		    _isRightMost = true,
		    _isBottomMost = true;

		if (this.tab != null)
			ctrls = parentObj.getTabControls(this.tab);
		else
			ctrls = parentObj.controls

		for (var cnt = 0; cnt < ctrls.length; cnt++)
		{
			var ctrl = ctrls[cnt];
			if ((ctrl === this) || (!ctrl.rect))
				continue;

			if ((parentObj === form) && (ctrl.constructor == JButton))
				continue;

			if ((ctrl.rect.left != null) && (ctrl.rect.left > (this.rect.left + this.rect.width)))
				_isRightMost = false;

			if ((ctrl.rect.top != null) && (ctrl.rect.top > (this.rect.top + this.rect.height)))
				_isBottomMost = false;
		}

		return { isRightMost: _isRightMost, isBottomMost: _isBottomMost };
	};

	this.disposeChildren = function()
	{
		if (this.controls != null)
		{
			this.controls.forEach(function(item)
			{
				if (item.dispose)
					item.dispose();
				else
					if (this.owner != null)
				{
					this.owner._debugAdd('object "' + item.name + '" has no dispose method. Type: ' + item.constructor);
				}

				if (this.owner != null)
					this.owner.unregisterObject(item);
			}, this);

			this.controls.clear();
		}

		if (this.datasets != null)
		{
			this.datasets.forEach(function(item)
			{
				if (item.dispose)
					item.dispose();

				if (this.owner != null)
					this.owner.unregisterObject(item);
			}, this);

			this.datasets.clear();
		}
	};

	this.getControlsByType = function(type)
	{
		if (type == null)
			return null;

		var items = [];
		this.controls.forEach(function(item)
		{
			if (item.constructor == type)
				items.push(item);
		}, this);

		return items;
	};

	this.$ = function(id)
	{
		if ((this.owner) && (this.owner.$))
			return this.owner.$(id);
		else
			return window.document.getElementById(id);
	};

	this.$$ = function(id)
	{
		if (id == null)
			return this.$(this.name);
		else
			return this.$(this.name + id);
	};

	this.getAllControls = function()
	{
		if (this.controls.length == 0)
			return [];

		var list = this.controls.concat();
		var subList = [];
		list.forEach(function(item)
		{
			if ((item != null) && (item.controls) && (item.controls.length) && (item.controls.length > 0))
				subList = subList.concat(item.getAllControls());
		}, self);

		return list.concat(subList);
	};

	this.getForm = function()
	{
		var obj = this;
		while (obj != null)
		{
			//			if (obj.constructor == JForm)
			//				break;
			if (obj.isForm)
				break;

			if (this.owner != null)
				obj = this.owner.getObject(obj.parent);
			else
				obj = null;
		}

		return obj;
	};

	this.getParentObject = function()
	{
		if (this.owner != null)
			return this.owner.getObject(this.parent);

		return null;
	};

	this.getRightMostChildControlPos = function()
	{
		var maxRight = 0;
		this.controls.forEach(function(control)
		{
			if ((control.rect) && (control.rect.left + control.rect.width > maxRight))
				maxRight = control.rect.left + control.rect.width;
		}, self);

		return maxRight;
	};

	this.getBottomMostChildControlPos = function()
	{
		var maxBottom = 0;
		this.controls.forEach(function(control)
		{
			if ((control.rect) && (control.rect.top + control.rect.height > maxBottom))
				maxBottom = control.rect.top + control.rect.height;
		}, self);

		return maxBottom;
	};

	this.set_visible = function(value)
	{
		this.visible = value;
		var elem = this.$(this.name);
		if (elem == null)
			return;

		var orgDisplay = elem.style.display;

		if (value)
			elem.style.display = 'block';
		else
			elem.style.display = 'none';

		if ((elem.style.display != orgDisplay) && (this.onvisibilitychanged))
			this.onvisibilitychanged.raise(value);

	};

	this.isInvisible = function()
	{
		return (this.dataset) && (this.dataset.isInvisible(this.field)) && (utils.inSet(efHideInvisible, this.flags));
	};

	this.dispose = function()
	{
		this.disposeChildren();

		this.owner = null;
		//		this.parent	= null;
		this.rect = null;
		this.field = null;
		this.dataset = null;
		this.controls = null;
		this.datasets = null;
	};
};


function formatDateTimeValue(dt, type, dateFormat, dateSeparator)
{
	if (utils.isEmpty(dt))
		return "";

	if (utils.isEmpty(dateFormat))
		dateFormat = 'dd.mm.yyyy'; 

	if (utils.isEmpty(dateSeparator))
		dateSeparator = '.';

	var day, month, year, h, m, s;
	var value = "";

	if (dt.constructor == String)
	{
		if (type == ftTime)
		{
			var splittedTime = dt.split(':');
			h = new Number(splittedTime[0]);
			m = new Number(splittedTime[1]);
			if (splittedTime.length > 2)
				s = new Number(splittedTime[2]);
			else
				s = 0;
			value = h.padLeft(2) + ':' + m.padLeft(2) + ':' + s.padLeft(2);

			return value;
		}

		var datOK = false;
		var splittedDT = dt.split(' ');
		var splittedDate = splittedDT[0].split('.');
		if (splittedDate.length > 1)
		{
			// suppose DD.MM.YYYY
			day = new Number(splittedDate[0]);
			month = new Number(splittedDate[1]);
			year = new Number(splittedDate[2]);
			datOK = true;
		}
		else
		{
			splittedDate = splittedDT[0].split('-');
			if (splittedDate.length > 1)
			{
				// suppose YYYY-MM-DD
				day = new Number(splittedDate[2]);
				month = new Number(splittedDate[1]);
				year = new Number(splittedDate[0]);
				datOK = true;
			}
			else
			{
				splittedDate = splittedDT[0].split('/');
				if (splittedDate.length > 1)
				{
					// suppose MM/DD/YYYY
					day = new Number(splittedDate[1]);
					month = new Number(splittedDate[0]);
					year = new Number(splittedDate[2]);
					datOK = true;
				}
			}
		}

		if (datOK)
		{
			switch (dateFormat)
			{
				case 'mm.dd.yyyy':
					value = month.padLeft(2) + dateSeparator + day.padLeft(2) + dateSeparator + year.padLeft(2);
					break;

				case 'dd.mm.yyyy':
				default:
					value = day.padLeft(2) + dateSeparator + month.padLeft(2) + dateSeparator + year.padLeft(2);
			}
			if ((type == ftDateTime) && (splittedDT.length > 1))
			{
				var timePart = formatDateTimeValue(splittedDT[1], ftTime);
				if (timePart != '00:00:00')
					value += ' ' + timePart;
			}
		}
	}
	else
	if (dt.constructor == Date)
	{
		switch (type)
		{
			case ftTime:
				value = dt.getHours().padLeft(2, '0') + ':' + dt.getMinutes().padLeft(2, '0') + ':' + dt.getSeconds().padLeft(2, '0');
				break;

			case ftDate:
			case ftDateTime:
				switch (dateFormat)
				{
					case 'mm.dd.yyyy':
						value = dt.getDate().padLeft(2) + dateSeparator + (dt.getMonth() + 1).padLeft(2) + '.' + dt.getFullYear().padLeft(2);
						break;

					case 'dd.mm.yyyy':
					default:
						value = dt.getDate().padLeft(2) + dateSeparator + (dt.getMonth() + 1).padLeft(2) + dateSeparator + dt.getFullYear().padLeft(2);
						break;
				}
				if (type == ftDateTime)
					value += ' ' + dt.getHours().padLeft(2, '0') + ':' + dt.getMinutes().padLeft(2, '0') + ':' + dt.getSeconds().padLeft(2, '0');
		}
	}

	return value;
}


if (typeof(loadNextScript) != 'undefined')
	loadNextScript();
